package mynme;

import java.time.format.DateTimeFormatter;
import java.util.*;

public interface FieldMonitorObserver {
    void update(SensorData data);
    String getObserverName();
}

// 主题接口
interface FieldMonitorSubject {
    void registerObserver(FieldMonitorObserver observer);
    void removeObserver(FieldMonitorObserver observer);
    void notifyObservers(SensorData data);
}

// 农田监测站
class FieldMonitorStation implements FieldMonitorSubject {
    private List<FieldMonitorObserver> observers = new ArrayList<>();
    private Map<String, SensorData> latestData = new HashMap<>();

    @Override
    public void registerObserver(FieldMonitorObserver observer) {
        observers.add(observer);
        System.out.println(observer.getObserverName() + " 已注册为观察者");
    }

    @Override
    public void removeObserver(FieldMonitorObserver observer) {
        observers.remove(observer);
        System.out.println(observer.getObserverName() + " 已移除观察者");
    }

    @Override
    public void notifyObservers(SensorData data) {
        latestData.put(data.getSensorId(), data);
        for (FieldMonitorObserver observer : observers) {
            observer.update(data);
        }
    }

    public void receiveSensorData(SensorData data) {
        System.out.println("\n监测站接收到 " + data.getDataType() + " 数据");
        data.display();
        notifyObservers(data);
    }

    public SensorData getLatestData(String sensorId) {
        return latestData.get(sensorId);
    }

    public void displayAllLatestData() {
        System.out.println("\n=== 最新传感器数据汇总 ===");
        if (latestData.isEmpty()) {
            System.out.println("暂无数据");
            return;
        }

        for (SensorData data : latestData.values()) {
            System.out.printf("%s - %s: %s%n",
                    data.getSensorId(),
                    data.getDataType(),
                    data.getFormattedValue());
        }
    }
}

// 具体观察者 - 数据存储观察者
class DataStorageObserver implements FieldMonitorObserver {
    private List<SensorData> storedData = new ArrayList<>();

    @Override
    public void update(SensorData data) {
        storedData.add(data);
        System.out.printf("[数据存储] %s 数据已保存 (总数: %d)%n",
                data.getDataType(), storedData.size());
    }

    @Override
    public String getObserverName() {
        return "数据存储系统";
    }

    public void displayStoredData() {
        System.out.println("\n=== 存储的所有传感器数据 ===");
        for (SensorData data : storedData) {
            System.out.printf("%s %s: %s%n",
                    data.getTimestamp().format(DateTimeFormatter.ISO_LOCAL_DATE_TIME),
                    data.getDataType(),
                    data.getFormattedValue());
        }
    }
}

// 具体观察者 - 报警观察者
class AlertObserver implements FieldMonitorObserver {
    @Override
    public void update(SensorData data) {
        // 土壤湿度警报
        if (data instanceof SoilMoistureData) {
            double moisture = ((SoilMoistureData)data).getValue();
            if (moisture < 20.0) {
                System.out.printf("[警报] %s 土壤湿度过低: %.1f%%%n",
                        data.getLocation(), moisture);
            } else if (moisture > 80.0) {
                System.out.printf("[警报] %s 土壤湿度过高: %.1f%%%n",
                        data.getLocation(), moisture);
            }
        }

        // 土壤pH值警报
        if (data instanceof SoilPHData) {
            double ph = ((SoilPHData)data).getValue();
            if (ph < 5.5) {
                System.out.printf("[警报] %s 土壤过酸: %.1f pH%n",
                        data.getLocation(), ph);
            } else if (ph > 7.5) {
                System.out.printf("[警报] %s 土壤过碱: %.1f pH%n",
                        data.getLocation(), ph);
            }
        }

        // 气象警报
        if (data instanceof WeatherData) {
            WeatherData weather = (WeatherData)data;
            if (weather.getWindSpeed() > 10.0) {
                System.out.printf("[警报] %s 风速过高: %.1f m/s%n",
                        data.getLocation(), weather.getWindSpeed());
            }
            if (weather.getTemperature() < 5.0) {
                System.out.printf("[警报] %s 温度过低: %.1f°C%n",
                        data.getLocation(), weather.getTemperature());
            }
        }

        // 作物健康警报
        if (data instanceof CropGrowthData) {
            int health = ((CropGrowthData)data).getHealthStatus();
            if (health < 4) {
                System.out.printf("[警报] %s 作物健康状况不佳: %d/10%n",
                        data.getLocation(), health);
            }
        }
    }

    @Override
    public String getObserverName() {
        return "警报系统";
    }
}

// 具体观察者 - 分析报告观察者
class AnalysisObserver implements FieldMonitorObserver {
    @Override
    public void update(SensorData data) {
        if (data instanceof SoilNutrientData) {
            SoilNutrientData nutrient = (SoilNutrientData)data;
            System.out.printf("[分析] %s 土壤养分分析 - N:%.1f, P:%.1f, K:%.1f mg/kg%n",
                    data.getLocation(),
                    nutrient.getNitrogen(),
                    nutrient.getPhosphorus(),
                    nutrient.getPotassium());

            // 简单肥料建议
            if (nutrient.getNitrogen() < 20.0) {
                System.out.println("[建议] 需要补充氮肥");
            }
            if (nutrient.getPhosphorus() < 15.0) {
                System.out.println("[建议] 需要补充磷肥");
            }
            if (nutrient.getPotassium() < 25.0) {
                System.out.println("[建议] 需要补充钾肥");
            }
        }
    }

    @Override
    public String getObserverName() {
        return "分析系统";
    }
}class FieldMonitor {
    private FieldMonitorStation monitorStation = new FieldMonitorStation();
    private DataStorageObserver storageObserver = new DataStorageObserver();
    private AlertObserver alertObserver = new AlertObserver();
    private AnalysisObserver analysisObserver = new AnalysisObserver();

    public FieldMonitor() {
        // 注册观察者
        monitorStation.registerObserver(storageObserver);
        monitorStation.registerObserver(alertObserver);
        monitorStation.registerObserver(analysisObserver);
    }

    public void showMenu() {
        Scanner scanner = new Scanner(System.in);
        while (true) {
            System.out.println("\n=== 农田环境监测 ===");
            System.out.println("1. 模拟土壤数据采集");
            System.out.println("2. 模拟作物生长监测");
            System.out.println("3. 模拟气象数据收集");
            System.out.println("4. 查看最新数据");
            System.out.println("5. 查看历史数据");
            System.out.println("0. 返回上级菜单");

            int choice = scanner.nextInt();
            scanner.nextLine(); // 消耗换行符

            switch (choice) {
                case 1:
                    simulateSoilData(scanner);
                    break;
                case 2:
                    simulateCropData(scanner);
                    break;
                case 3:
                    simulateWeatherData(scanner);
                    break;
                case 4:
                    monitorStation.displayAllLatestData();
                    break;
                case 5:
                    storageObserver.displayStoredData();
                    break;
                case 0:
                    return;
                default:
                    System.out.println("无效选择，请重新输入！");
            }
        }
    }

    private void simulateSoilData(Scanner scanner) {
        System.out.println("\n=== 模拟土壤数据采集 ===");
        System.out.println("输入传感器ID:");
        String sensorId = scanner.nextLine();

        System.out.println("输入位置(如: A1地块):");
        String location = scanner.nextLine();

        System.out.println("选择数据类型: 1.湿度 2.pH值 3.养分含量");
        int type = scanner.nextInt();

        switch (type) {
            case 1:
                System.out.println("输入土壤湿度(%):");
                double moisture = scanner.nextDouble();
                monitorStation.receiveSensorData(
                        new SoilMoistureData(sensorId, location, moisture));
                break;
            case 2:
                System.out.println("输入土壤pH值:");
                double ph = scanner.nextDouble();
                monitorStation.receiveSensorData(
                        new SoilPHData(sensorId, location, ph));
                break;
            case 3:
                System.out.println("输入氮含量(mg/kg):");
                double nitrogen = scanner.nextDouble();
                System.out.println("输入磷含量(mg/kg):");
                double phosphorus = scanner.nextDouble();
                System.out.println("输入钾含量(mg/kg):");
                double potassium = scanner.nextDouble();
                monitorStation.receiveSensorData(
                        new SoilNutrientData(sensorId, location,
                                nitrogen, phosphorus, potassium));
                break;
            default:
                System.out.println("无效类型！");
        }
    }

    private void simulateCropData(Scanner scanner) {
        System.out.println("\n=== 模拟作物生长监测 ===");
        System.out.println("输入传感器ID:");
        String sensorId = scanner.nextLine();

        System.out.println("输入位置(如: A1地块):");
        String location = scanner.nextLine();

        System.out.println("输入植株高度(cm):");
        double height = scanner.nextDouble();

        System.out.println("输入叶面积(cm²):");
        double leafArea = scanner.nextDouble();

        System.out.println("输入健康状态(1-10):");
        int health = scanner.nextInt();

        monitorStation.receiveSensorData(
                new CropGrowthData(sensorId, location, height, leafArea, health));
    }

    private void simulateWeatherData(Scanner scanner) {
        System.out.println("\n=== 模拟气象数据收集 ===");
        System.out.println("输入传感器ID:");
        String sensorId = scanner.nextLine();

        System.out.println("输入位置(如: A1地块):");
        String location = scanner.nextLine();

        System.out.println("输入温度(°C):");
        double temp = scanner.nextDouble();

        System.out.println("输入湿度(%):");
        double humidity = scanner.nextDouble();

        System.out.println("输入风速(m/s):");
        double windSpeed = scanner.nextDouble();

        monitorStation.receiveSensorData(
                new WeatherData(sensorId, location, temp, humidity, windSpeed));
    }
}

